package com.openatc.agent.service.impl;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.openatc.agent.service.AscsDao;
import com.openatc.agent.service.GenericMsgStrategy;
import com.openatc.agent.utils.RedisTemplateUtil;
import com.openatc.comm.data.MessageData;
import com.openatc.core.model.InnerError;
import com.openatc.core.model.RESTRet;
import com.openatc.core.util.DateUtil;
import com.openatc.core.util.RESTRetUtils;
import com.openatc.model.model.StatusPattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import static com.openatc.core.common.IErrorEnumImplInner.E_110;
import static com.openatc.core.common.IErrorEnumImplOuter.E_2013;

/**
 * @Classname GetStatusPattern
 * @Description 处理平台发送的方案状态请求
 * @Date 2022/7/19 13:41
 * @Created by panleilei
 */
@Service(value = "status/pattern")
public class StatusPatternRequest extends GenericMsgStrategy {
    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    @Autowired
    private AscsDao ascsDao;

    private String keyType = "response:status/pattern:";

    @Value("${agent.comm.pattern.cache}")
    private boolean patternCache;


    @Override
    public RESTRet preProcess(MessageData msg) {

        // 未开启消息缓存，则直接从设备查询方案消息
        if(!patternCache)
            return super.preProcess(msg);

//        return RESTRetUtils.successObj(null);

        // OpenATC 5.0 - status/pattern 的请求都从缓存中获取
        MessageData responseData = null;
        responseData = ascsDao.getStatusPatternFromMap(msg.getAgentid());

        if(responseData == null){
            return RESTRetUtils.errorObj(false,E_2013);
        }

        JsonObject msgdata = new JsonObject();
        JsonArray msgphase = new JsonArray();
        msgdata.add("phase",msgphase);

        try {
            // 删除不需要的数据
            JsonObject mdo = responseData.getData().getAsJsonObject();

            msgdata.add("mode",mdo.get("mode"));
            msgdata.add("control",mdo.get("control"));
            msgdata.add("patternid",mdo.get("patternid"));
            msgdata.add("cycle",mdo.get("cycle"));
            msgdata.add("patternoffset",mdo.get("patternoffset"));
            msgdata.add("overlap",mdo.get("overlap"));
            msgdata.add("stages",mdo.get("stages"));
            msgdata.add("stages_len",mdo.get("stages_len"));
            msgdata.add("stages_seq",mdo.get("stages_seq"));
            msgdata.add("stages_cur",mdo.get("stages_cur"));
            msgdata.add("current_stage",mdo.get("current_stage"));
            msgdata.add("current_stagecd",mdo.get("current_stagecd"));
            msgdata.add("offset",mdo.get("offset"));
            msgdata.add("current_phase",mdo.get("current_phase"));
            msgdata.add("next_phase",mdo.get("next_phase"));
            msgdata.add("rings",mdo.get("rings"));


            // 计算周期时间
            int second = DateUtil.getBetweenDatesFromNow(responseData.getSts());
            JsonElement mdocd = mdo.get("curTime");
            JsonElement mdopcd = mdo.get("syncTime");

            if( mdocd != null)
                msgdata.addProperty("curTime", mdocd.getAsInt() + second);

            if( mdopcd != null)
                msgdata.addProperty("syncTime", Math.max(mdopcd.getAsInt() - second, 0));

            // 计算阶段倒计时
//            JsonElement current_stagecd = mdo.get("current_stagecd");
//
//            if( current_stagecd != null){
//                int countdown = current_stagecd.getAsInt();
//                countdown = countdown - second;
//                msgdata.addProperty("current_stagecd", Math.max(countdown, 0));
//            }

            // 设置相位信息
            if(mdo.get("phase") != null){
                JsonArray phases = mdo.get("phase").getAsJsonArray();
                for (JsonElement phase : phases) {
                    JsonObject phosedatanew = new JsonObject();
                    msgphase.add(phosedatanew);

                    JsonObject phosedata = phase.getAsJsonObject();
                    phosedatanew.add("id",phosedata.get("id"));
                    phosedatanew.add("split",phosedata.get("split"));
                    phosedatanew.add("type",phosedata.get("type"));
                    phosedatanew.add("pedtype",phosedata.get("pedtype"));

                    // 计算倒计时
                    JsonElement cd = phosedata.get("countdown");
                    JsonElement pcd = phosedata.get("pedcountdown");
                    if( cd != null){
                        int countdown = cd.getAsInt();
                        countdown = countdown - second;
                        phosedatanew.addProperty("countdown", Math.max(countdown, 0));

                    }
                    if( pcd != null){
                        int pedcountdown = pcd.getAsInt();
                        pedcountdown = pedcountdown - second;
                        phosedatanew.addProperty("pedcountdown", Math.max(pedcountdown, 0));
                    }
                }
            }

        }catch (Exception e){
            logger.warning("pattern preProcess error:" + e.getMessage() + " data:" + responseData);
        }

        msg.setData(msgdata);
        return RESTRetUtils.successObj(msg);
    }


    /**
     * 信号机成功应答请求
     * @param requestData
     * @param responseData
     * @return
     */
    @Override
    public RESTRet successGetProcess(MessageData requestData, RESTRet responseData) {
        String agentid = requestData.getAgentid();
        MessageData res = (MessageData) responseData.getData();
        // 保存到redis
        String key = keyType + agentid;
        res.setCreatetime(String.valueOf(System.currentTimeMillis()));
        redisTemplateUtil.setValue(key,gson.toJson(res));
        return super.successGetProcess(requestData,responseData);
    }


    /** 信号机应答失败
     * @param requestData
     * @param responseData
     * @return
     */
    @Override
    public RESTRet failureGetProcess(MessageData requestData, RESTRet responseData) {

        InnerError innerError = (InnerError) responseData.getData();
        // 上次请求未结束/请求超时,从缓存中获取数据
        if (innerError.getErrorCode().equals(E_110.getErrorCode()) ) {

            RESTRet rest = redisTemplateUtil.getCacheData(requestData);
            return rest;
        }

        return super.failureGetProcess(requestData, responseData);
    }
}
